package chess;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;


import game.KnightsTourGame;

/**
 * This class will test the knights tour game by completing a full game and solving the entire game
 * The algorithm is based on Warnsdorff's Rule for solving Knights Tour
 * @author Caleb Chan
 * <pre>
 * - Created February 17, 2010
 * </pre>
 */
public class TestKnightsTourPlayer extends Player {
	
	private KnightsTourGame game;
	private ArrayList<command.Command> listOfMoves;
	private int numOfMoves;
	
	/**
	 * Creates a player to test the game
	 * @param game Take a game object for tile computations
	 * <pre>
	 * Caleb Chan
	 * - Created February 17, 2010
	 * </pre>
	 */
	public TestKnightsTourPlayer(String playerName,KnightsTourGame game, String color){
		super("Knights Tour Tester",game,"Black");
		this.game = game;
		listOfMoves = new ArrayList<command.Command>();
		numOfMoves = 0;
	}
	/**
	 * Return the number of moves that the test player has accomplished
	 * @return Returns the number of moves
	 * <pre>
	 * Caleb Chan
	 * - Created February 17, 2010
	 * </pre>
	 */
	public int getNumberOfMoves(){
		return numOfMoves;
	}
	/**
	 * It overrides the takeTurn method in player and plays through a normal turn for knights 
	 * tour
	 * <pre>
	 * Caleb Chan
	 * - Created February 17, 2010
	 * </pre>
	 * @deprecated This method is replaced by the methods used in KnightsTourTestView
	 */
	public void takeTurn(){
	}
	
	/**
	 * This will take a list of moves that a knight can make an computes the best position for the 
	 * next move the knight should make. It places a dummy knight at each of the valid 
	 * moves. Then it calculates the number of valid moves that dummy knight can make. It does this 
	 * for each of the moves in the moveList list. Then it sorts the list in ascending order. Then it
	 * return the tile with the lowest number of valid moves.
	 * @param moveList A list of valid moves a knight can make
	 * @return Return the next tile that the knight should make
	 * <pre>
	 * Caleb Chan
	 * - Created February 17, 2010
	 * </pre>
	 */
	@SuppressWarnings("unchecked")
	public Tile nextMove(ArrayList<Tile> moveList){
		ArrayList<TestKnightsTourPlayerHelper> moves = new ArrayList<TestKnightsTourPlayerHelper>();
		for(Tile t : moveList){
			moves.add(new TestKnightsTourPlayerHelper(t,game,this));
		}
		Collections.sort(moves, new KnightTourComparator());
		return (moves.size() == 0)?null:moves.get(0).getTile();
	}
	public void increaseMoves(){
		numOfMoves++;
	}
	
	/**
	 * This class is a helper class for the TestKnightsTourPlayer. It holds a tile and 
	 * the number of valid moves that a knight could make if it was on that tile.
	 * @author Caleb Chan
	 * <pre>
	 * - Created February 17, 2010
	 * </pre>
	 */
	private class TestKnightsTourPlayerHelper{
		private int availableMoves;
		private Tile tile;
		private KnightsTourGame game;
		/**
		 * Creates a TestKnightsTourPlayerHelper object
		 * @param tile The current tile to calculate available moves
		 * @param game The currently played game
		 * @param player The current player playing the game
		 * <pre>
		 * Caleb Chan
		 * - Created February 17, 2010
		 * </pre>
		 */
		public TestKnightsTourPlayerHelper(Tile tile, KnightsTourGame game,Player player){
			this.tile = tile;
			this.game = game;
			calculateNumberOfMoves(player);
		}
		/**
		 * This calculates the number of available moves that a knight in the tile can move
		 * @param player The current player playing the game
		 * <pre>
		 * Caleb Chan
		 * - Created February 17, 2010
		 * </pre>
		 */
		public void calculateNumberOfMoves(Player player){
			tile.setPieceHere(new KnightPiece(player,tile));
			ArrayList<Tile> movementTiles = tile.getPieceHere().getMovementTiles();
			game.filterMovementTiles(movementTiles);
			availableMoves = movementTiles.size();
			tile.setPieceHere(null);
		}
		/**
		 * Returns the number of moves 
		 * @return Returns the number of moves
		 * <pre>
		 * Caleb Chan
		 * - Created February 17, 2010
		 * </pre>
		 */
		public int getAvailableMoves(){
			return availableMoves;
		}
		/**
		 * Returns the current tile
		 * @return Returns the current tile
		 * <pre>
		 * Caleb Chan
		 * - Created February 17, 2010
		 * </pre>
		 */
		public Tile getTile(){
			return tile;
		}
	}
	/**
	 * This class is used for comparing the different tiles and sorting
	 * @author Caleb Chan
	 * <pre>
	 * - Created February 17, 2010
	 * </pre>
	 */
	private class KnightTourComparator implements Comparator{
		/**
		 * This method will compare 2 objects and return an positive if the first object is 
		 * greater then the first, a negative integer if the second one is greater and zero if 
		 * they are both equal.
		 * @param ob1 A TestKnightsTourPlayerHelper object
		 * @param ob1 Another TestKnightTourPlayerHelper object
		 * <pre>
		 * Caleb Chan
		 * - Created February 17, 2010
		 * </pre> 
		 */
		public int compare(Object ob1, Object ob2){
			if(ob1 == null||ob2 == null){
				return 0;
			}
			if (!(ob1 instanceof TestKnightsTourPlayerHelper)||!(ob1 instanceof TestKnightsTourPlayerHelper)){
				return 0;
			}
			TestKnightsTourPlayerHelper helper1 = (TestKnightsTourPlayerHelper)ob1;
			TestKnightsTourPlayerHelper helper2 = (TestKnightsTourPlayerHelper)ob2;
			return helper1.getAvailableMoves() - helper2.getAvailableMoves();
		}
		/**
		 * This method will compare if two comparator objects are equal.
		 * @param A comparator object
		 * <pre>
		 * Caleb Chan
		 * - Created February 17, 2010
		 * </pre>
		 */
		public boolean equals(Object ob1){
			return true;
		}
	}
}

